
package com.apestech.framework.sql.table;

import com.apestech.framework.cache.Cache;
import com.apestech.framework.dictionary.modul.ImportedKey;
import com.apestech.framework.dictionary.modul.Table;
import com.apestech.framework.json.JSONObject;
import com.apestech.framework.sql.SqlUtil;
import com.apestech.framework.sql.callback.OSqlCallback;
import com.apestech.framework.sql.condition.ConditionMap;
import com.apestech.framework.sql.modul.SqlList;
import com.apestech.framework.util.ExceptionUtil;
import com.apestech.framework.xml.sql.modul.SqlRule;

import java.util.ArrayList;

/**
 * @author hup
 * @create 2018-08-30-11:56
 */
public class TableSelect extends SqlUtil {

    public class SubSql {
        private String select;
        private String from;

        public SubSql(String select, String from){
            this.select=select;
            this.from=from;
        }

        public String getSelect() {
            return select;
        }

        public String getFrom() {
            return from;
        }
    }

    private String sql;
    private ConditionMap param;
    private SqlList sqlparam=new SqlList();
    private String schema;
    private OSqlCallback oSqlCallback;

    public TableSelect(ConditionMap param) throws Exception {
        this.param=param;
    }

    public void setSqlparam(SqlList sqlparam) {
        this.sqlparam = sqlparam;
    }

    public void setSchema(String schema) {
        this.schema = schema;
    }

    public void getTableSql() throws Exception {
        sqlparam=new SqlList();
        sql= (String) Cache.getKey(param.getCacheKey());
        sql=null;
        if(sql==null){
            String select="";
            String from="";
            int len=param.getFromtab().size();
            for(int i=0; i<len; i++){
                String tabName=param.getFromtab().getTable(i);
                if(schema!=null && i==0) tabName=schema+"."+tabName;
                SubSql subsql=getSelectCol(tabName, param.getFromtab().getAlias(i));
                if(subsql!=null){
                    if(!"".equals(select)) select=select+",";
                    if(!"".equals(from)) from=from+",";
                    select=select+subsql.getSelect();
                    from=from+subsql.getFrom();
                }
            }
            sql="SELECT "+select+" FROM "+from+" WHERE 1=1 ";
            Cache.setKey(param.getCacheKey(), sql);
        }
        String where=param.getExecSql();
        if(where!=null && !"".equals(where)) sql=sql+where;
        String tabName=param.getFromtab().getTable(0);
        if(param.isKeyWhere()){
            if(schema!=null) tabName=schema+"."+tabName;
            Table tab=param.getFromtab().getDictTable(tabName);
            String k=tab.getPkKey().getPkColumn();
            sql=sql+getKeyWhere(k, false, k, param.getTimeField(), param.isTimeControl());
        }
        if(oSqlCallback!=null){
            sql=sql+oSqlCallback.getSql();
        }
        sql=addSql(param.getFromtab(), sql, param, sqlparam, "");
        //sqlparam.add(sql);
    }

    private SubSql getSelectCol(String tabName, String alais) throws Exception {
        String cols=null;
        String fkey="";
        String from="";
        try {
            String fields=param.getSqlruleFields(tabName);
            boolean in=!param.getSqlruleNotIn(tabName);
            boolean fk=param.getSqlruleForeignKey(tabName);
            Table table=param.getFromtab().getDictTable(tabName);
            SqlRule.Table sqltab=param.getSqlruleTable(tabName);
            if("".equals(alais)) alais="A";
            from=tabName+" "+alais;
            if(!"".equals(alais)) alais=alais+".";
            String col=getCol(table.getColumn(), fields, in);
            if(alais!=null && !"".equals(alais)) cols=alais+col.replace(",",","+alais);
            else cols=col;
            if(sqltab!=null && sqltab.getField()!=null){
                int len=sqltab.getField().size();
                ArrayList<String> klist=sqltab.getField().getKeylist();
                for(int i=0; i<len; i++){
                    String k=klist.get(i);
                    JSONObject m= (JSONObject) sqltab.getField().get(k);
                    String nbsql=getSelectSql(m);
                    String falaisField=m.getString("alaisField");
                    if(falaisField==null) falaisField="T_"+k;
                    if(nbsql!=null){
                        nbsql=nbsql.replace("#{KEY}", alais+k);
                        cols=cols+",("+nbsql+") AS "+falaisField;
                    }
                }
            }
            if(fk){
                String falais=alais;
                if("".equals(alais)) falais=tabName+".";
                ImportedKey fkmap=table.getPkFKey();
                if(fkmap!=null){
                    if(fields!=null){
                        fields=","+fields+",";
                    }
                    ArrayList<String> fklist=fkmap.getField().getKeylist();
                    int len=fklist.size();
                    for(int i=0; i<len; i++){
                        String key=fklist.get(i);
                        boolean flag=true;
                        if(fields!=null){
                            if(in && (fields).indexOf(key)<0) flag=false;
                            if(!in && (fields).indexOf(key)>=0) flag=false;
                        }
                        if(flag){
                            String colName=fkmap.getPkColumnName(key);
                            String ftabName=fkmap.getPkTableName(key);
                            String dColName=fkmap.getColumnName(key);
                            Table ftab= param.getFromtab().getDictTable(ftabName);
                            if(ftab!=null && !tabName.equals(ftabName)){
                                ftabName=ftabName.toUpperCase();
                                if(ftab.getField().get("NAME")!=null){
                                    String colCName="";
                                    if(dColName.indexOf(",")>=0) colCName=dColName.replace(",","_");
                                    else colCName=dColName.substring(0, dColName.length()-2)+"NAME";
                                    if(!"".equals(fkey)){
                                        fkey=fkey+",";
                                    }
                                    fkey=fkey+" (SELECT Z.NAME FROM "+ftabName+" Z WHERE ";
                                    if(dColName.indexOf(",")>=0){
                                        fkey=fkey+" 1=1 ";
                                        String[] dlist=dColName.split(",");
                                        String[] flist=colName.split(",");
                                        int dlen=dlist.length;
                                        for(int d=0; d<dlen; d++){
                                            fkey=fkey+" AND "+falais+dlist[d]+"=Z."+flist[d]+" ";
                                        }
                                    }
                                    else fkey=fkey+falais+key+"=Z."+colName;
                                    fkey=fkey+") AS "+colCName;
                                } else if(param.getSqlCallback()!=null){
                                    String where=param.getSqlCallback().getChildSelect(key, colName, ftabName, ftab);
                                    if(where==null){
                                        where="";
                                    }
                                    if(!"".equals(where.trim())){
                                        if(!"".equals(fkey)){
                                            fkey=fkey+",";
                                        }
                                        fkey=fkey+" "+where+" ";
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if(!"".equals(cols)) {
                if(!"".equals(fkey)) cols=cols+","+fkey;
                return new SubSql(cols, from);
            }
        } catch (Exception e) {
            ExceptionUtil.exception(this, "getSelect", e.getMessage());
        }
        return null;
    }

    public String getSql() {
        return sql;
    }

    public SqlList getSqlparam() {
        return sqlparam;
    }

    public void setoSqlCallback(OSqlCallback oSqlCallback) {
        this.oSqlCallback = oSqlCallback;
    }
}
